package com.tianxiabuyi;

import com.alibaba.fastjson.TypeReference;
import com.tianxiabuyi.utils.Crypt;
import com.tianxiabuyi.utils.IpUtil;
import com.tianxiabuyi.utils.JSONUtil;
import com.tianxiabuyi.utils.Tools;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 包装request对象
 * @author yangh
 */
public class Input {
    /** request对象 */
    private HttpServletRequest request;
    /** 参数列表map对象 */
    private Map<String, String> parameters = new HashMap<String, String>();
    /** 请求端ip */
    private String ip;
    /** 请求端user-agent */
    private String useragent;
    /** 所有请求参数string */
    private String params;
    /** 请求的资源路径 */
    private String path;
    /** 请求端类型 */
    private String clientType;

    /**
     * 构造Input对象
     */
    public Input() {
    }

    /**
     * 使用request构造Input对象
     * @param request request请求
     */
    public Input(HttpServletRequest request) {
        this.request = request;
        init();
    }

    public Input setDesc(String parameter, String value) {
        parameter = Tools.getDesc(parameter, "");
        value = Tools.getDesc( value, "");
        if ((!"".equals(parameter)) && (!"".equals(value))) {
            this.getParameters().put(parameter, value);
        }
        return this;
    }

    /**
     * 设置input内容
     * @param parameters
     * @return
     */
    public Input setDescs(Map<String, String> parameters) {
        Iterator<Map.Entry<String, String>> it = parameters.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String, String> entry = it.next();
            String key = entry.getKey();
            String value = entry.getValue();
            // 去除空串的内容
            if ("".equals(key) || "".equals(value)) {
                it.remove();
            }
        }
        this.parameters.clear();
        this.getParameters().putAll(parameters);
        return this;
    }

    /**
     * 初始化，将request中的键值对放入map中
     */
    private void init() {
        parameters = new HashMap<String, String>();
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            // 去除空串的内容
            if (request.getParameter(name) == null || "".equals(request.getParameter(name)))
                continue;
            parameters.put(name, request.getParameter(name));
        }
    }

    /**
     * 获取请求端类型<br/>
     * 苹果设备 微信客户端 其他都为安卓
     * @return 请求端类型
     */
    public String getClientType() {
        String clientType = this.getUseragent().toLowerCase();
        if (clientType.contains("micromessenger")) {
            return "wechat";
        } else if (clientType.contains("iphone")) {
            return "iPhone";
        }
        return "Android";
    }

    /**
     * 获取请求资源路径
     * @return 请求资源路径
     */
    public String getPath() {
        return request.getServletPath();
    }


    /**
     * 获取请求端ip地址
     * @return ip地址
     */
    public String getIp() {
        return IpUtil.getClientIp(request);
    }

    /**
     * 获取请求端user-agent
     * @return user-agent
     */
    public String getUseragent() {
        return request.getHeader("user-agent");
    }

    /**
     * 获取request
     * @return request
     */
    public HttpServletRequest getRequest() {
        return request;
    }

    /**
     * 设置request
     * @param request request
     */
    public void setRequest(HttpServletRequest request) {
        this.request = request;
        init();
    }

    /**
     * 以键值对方式返回请求参数
     * @return
     */
    public Map<String, String> getParameters() {
        return parameters;
    }

    /**
     * 从请求头中取出对应的值
     * @param header 请求头名称
     * @return 请求头中取出对应的值
     */
    public String getHeader(String header) {
        return request.getHeader(header);
    }

    public Integer getInt(String name) {
        return Tools.getInt(parameters.get(name), -9999);
    }

    public Integer getInt(Integer name) {
        return getInt(parameters.get(name));
    }

    public Integer getInt(Integer name, Integer defaultV) {
        return getInt(parameters.get(name), defaultV);
    }

    public Integer getInt(String name, Integer defaultV) {
        return Tools.getInt(parameters.get(name), defaultV);
    }

    public Integer getInt(String name, Integer min, Integer max,
                          Integer defaultV) {
        return Tools.getInt(parameters.get(name), defaultV);
    }

    public String getString(String name) {
        return Tools.getDesc(parameters.get(name), "");
    }

    public String getDesc(String name) {
        return Tools.getDesc(parameters.get(name));
    }

    public Long getLong(String name) {
        return Tools.getLong(parameters.get(name));
    }

    public Long getLong(String name, Long defaultV) {
        return Tools.getLong(parameters.get(name), defaultV);
    }

    public Double getDouble(String name) {
        return Tools.getDouble(parameters.get(name));
    }

    public Double getDouble(String name, Double defaultV) {
        return Tools.getDouble(parameters.get(name), defaultV);
    }

    public Float getFloat(String name) {
        return Tools.getFloat(parameters.get(name));
    }

    public Float getFloat(String name, Float defaultV) {
        return Tools.getFloat(parameters.get(name), defaultV);
    }

    public String getDesc(String name, String defaultV) {
        return Tools.getDesc(parameters.get(name), defaultV);
    }


    /**
     * 验证客户端请求是否以标准JSON格式，并且加密传递<br/>
     * 只有以下这种请求方式才能通过验证，过滤一些非法请求<br/>
     * String param = "{\"userName\":\"userName\",\"password\":\"password\"}";<br/>
     * String url = "http://api.365jilu.com/login?json="+加密(param);
     * @return
     */
    public Message validate() {
        Message message = new Message(0, "JSON验证通过");
        try {
            // 解密客户端数据
            String jsonCrypt = this.getDesc("json", "");
            if ("".equals(jsonCrypt)) {
                message.setErrcode(10001);
                return message;
            }
            try {
                jsonCrypt = Crypt.decryptStr(jsonCrypt);
            } catch (Exception e) {
                message.setErrcode(10001);
                return message;
            }
            Map<String, String> jsonMap = JSONUtil.fromJson(jsonCrypt, new TypeReference<Map<String,String>>() {});
            if (null == jsonMap) { // 客户端传来的json不规范
                jsonMap = new HashMap<String, String>();
                message.setErrcode(10001);
                return message;
            }
            this.setDescs(jsonMap); // 解密后的字段赋值给input
            this.parameters.remove("json");
        } catch (Exception e) {
            System.out.println("Exception");
            message.setErrcode(10002);
            return message;
        }
        return message;

    }

    /**
     * 请求转发
     * @param action 被转发的地址
     * @param response HttpServletResponse对象
     * @param out JspWriter对象
     * @throws Exception 被转发的地址找不到
     */
    public void route(String action, HttpServletResponse response, JspWriter out) throws Exception {
        Message message = this.validate();
        int errCode = message.getErrcode();
        if (0 != errCode) { // 验证不通过
            Tools.encryptPrint(out, message);
            return;
        }

        // 医院id
        String hospital = this.getDesc("hospital");
        // 默认为公众版
        String appType = this.getDesc("app_type", "patient");
        // 转发到对应医院的接口
        HttpServletRequest request = this.getRequest();
        request.getRequestDispatcher("/"+ appType +"/" + hospital + action).forward(request, response);
    }
    /**
     * 获取请求参数字符串，以url中的参数形式拼接
     * @return url参数
     */
    public String getParams() {
        if (parameters.get("json") != null) {
            try {
                String decryptStr = Tools.decryptStr(parameters.get("json"));
                Map<String, String> jsonMap = JSONUtil.fromJson(decryptStr, new TypeReference<HashMap<String, String>>() {});
                return Tools.genUrlParams(jsonMap);
            } catch (Exception e) {

            }
        }

        return Tools.genUrlParams(parameters);
    }
    @Override
    public String toString() {
        return this.getParameters().toString();
    }
}